package cn.yunyichina.provider.pay.wechat.service.impl;

import cn.yunyichina.provider.iface.entity.common.ResponseObject;
import cn.yunyichina.provider.pay.wechat.common.XMLUtil;
import cn.yunyichina.provider.pay.wechat.config.Wechat;
import cn.yunyichina.provider.pay.wechat.constant.ResponseEnum;
import cn.yunyichina.provider.pay.wechat.entity.common.*;
import cn.yunyichina.provider.pay.wechat.service.BaseService;
import cn.yunyichina.provider.pay.wechat.service.WechatAuthService;
import cn.yunyichina.utils.commons.HttpUtil;
import cn.yunyichina.utils.convert.JsonUtils;
import cn.yunyichina.utils.security.SignUtil;
import org.dom4j.DocumentException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.util.Map;

/**
 * Created by Lullaby on 2016/10/17.
 */
@Service
public class WechatAuthServiceImpl extends BaseService implements WechatAuthService {

    private static final Logger logger = LoggerFactory.getLogger(WechatAuthServiceImpl.class);

    /**
     * 获取微信access_token
     *
     * @param data
     * @return
     */
    public ResponseObject getWechatAuth(String data) {
        logger.info("WechatAuthServiceImpl.getWechatAuth.data -> {}", data);

        ResponseObject response = new ResponseObject();

        Map<String, String> params = JsonUtils.parseObject(data, Map.class);

        String appid = params.get("app_id");
        String appSecret = params.get("app_secret");
        String code = params.get("auth_code");

        String url = "https://api.weixin.qq.com/sns/oauth2/access_token" +
                "?appid=" + appid +
                "&secret=" + appSecret +
                "&code=" + code +
                "&grant_type=authorization_code";

        logger.info("WechatAuthServiceImpl.getWechatAuth.url -> {}", url);
        try {
            String result = HttpUtil.get(url);
            logger.info("WechatAuthServiceImpl.getWechatAuth.result -> {}", result);

            WechatAuthResponse auth = JsonUtils.parseObject(result, WechatAuthResponse.class);

            if (auth != null && !StringUtils.isEmpty(auth.getAccessToken()) && !StringUtils.isEmpty(auth.getOpenid())) {
                response.setResultObject(auth);
            } else {
                response.setResultCodeAndMessageAndResult(
                        ResponseEnum.WECHAT_ACCESS_TOKEN_FAILURE.getCode(),
                        ResponseEnum.WECHAT_ACCESS_TOKEN_FAILURE.getMessage(),
                        getWechatErrcodeAndmsg(JsonUtils.parseObject(result, WechatCommonResponse.class))
                );
            }
        } catch (IOException e) {
            response.setResultCodeAndMessage(
                    ResponseEnum.WECHAT_ACCESS_TOKEN_EXCEPTION.getCode(),
                    ResponseEnum.WECHAT_ACCESS_TOKEN_EXCEPTION.getMessage()
            );

            logger.error("WechatAuthServiceImpl.getWechatAuth.exception", e);
        }

        return response;
    }

    /**
     * 获取微信普通access_token
     *
     * @param data
     * @return
     */
    public ResponseObject getWechatAuthAccessToken(String data) {
        logger.info("WechatAuthServiceImpl.getWechatAutAccessToken.data -> {}", data);

        ResponseObject response = new ResponseObject();

        Map<String, String> params = JsonUtils.parseObject(data, Map.class);

        String appid = params.get("appid");
        String secret = params.get("secret");
        String grantType = params.get("grant_type");

        String url = "https://api.weixin.qq.com/cgi-bin/token" +
                "?grant_type=" + grantType +
                "&appid=" + appid +
                "&secret=" + secret;

        logger.info("WechatAuthServiceImpl.getWechatAutAccessToken.url -> {}", url);
        try {
            String result = HttpUtil.get(url);
            logger.info("WechatAuthServiceImpl.getWechatAutAccessToken.result -> {}", result);

            WechatAccessTokenResponse accessTokenResponse = JsonUtils.parseObject(result, WechatAccessTokenResponse.class);

            if (accessTokenResponse != null &&
                    !StringUtils.isEmpty(accessTokenResponse.getAccessToken()) &&
                    !StringUtils.isEmpty(accessTokenResponse.getExpiresIn())) {
                response.setResultObject(accessTokenResponse);
            } else {
                response.setResultCodeAndMessageAndResult(
                        ResponseEnum.WECHAT_ACCESS_TOKEN_FAILURE.getCode(),
                        ResponseEnum.WECHAT_ACCESS_TOKEN_FAILURE.getMessage(),
                        getWechatErrcodeAndmsg(JsonUtils.parseObject(result, WechatCommonResponse.class))
                );
            }
        } catch (IOException e) {
            response.setResultCodeAndMessage(
                    ResponseEnum.WECHAT_ACCESS_TOKEN_EXCEPTION.getCode(),
                    ResponseEnum.WECHAT_ACCESS_TOKEN_EXCEPTION.getMessage()
            );

            logger.error("WechatAuthServiceImpl.getWechatAutAccessToken.exception", e);
        }

        return response;
    }

    /**
     * 获取微信医疗支付access_token
     *
     * @param data
     * @return
     */
    public ResponseObject getWechatAuthMedicalAccessToken(String data) {
        logger.info("WechatAuthServiceImpl.getWechatAuthMedicalAccessToken.data -> {}", data);

        ResponseObject response = new ResponseObject();

        Map<String, String> params = JsonUtils.parseObject(data, Map.class);

        String grantType = params.get("grant_type");
        String appId = params.get("appid");
        String agentAppId = params.get("agentappid");
        String agentSecret = params.get("agentsecret");

        String url = "https://api.weixin.qq.com/payinsurance/gettoken" +
                "?grant_type=" + grantType +
                "&agentappid=" + agentAppId +
                "&agentsecret=" + agentSecret +
                "&appid=" + appId;

        logger.info("WechatAuthServiceImpl.getWechatAuthMedicalAccessToken.url -> {}", url);
        try {
            String xmlResult = HttpUtil.get(url);
            logger.info("WechatAuthServiceImpl.getWechatAuthMedicalAccessToken.xmlResult -> {}", xmlResult);

            Map<String, String> mapResult = XMLUtil.xmlToMap(xmlResult);
            logger.info("WechatAuthServiceImpl.getWechatAuthMedicalAccessToken.mapResult -> {}", JsonUtils.toJsonString(mapResult));

            WechatAccessTokenResponse accessTokenResponse = JsonUtils.parseObject(mapResult, WechatAccessTokenResponse.class);
//            accessTokenResponse.setAccessToken("thisiswechatmedicalaccesstoken");
//            accessTokenResponse.setExpiresIn("7200");

            if (accessTokenResponse != null &&
                    !StringUtils.isEmpty(accessTokenResponse.getAccessToken()) &&
                    !StringUtils.isEmpty(accessTokenResponse.getExpiresIn())) {
                response.setResultObject(accessTokenResponse);
            } else {
                response.setResultCodeAndMessageAndResult(
                        ResponseEnum.WECHAT_ACCESS_TOKEN_FAILURE.getCode(),
                        ResponseEnum.WECHAT_ACCESS_TOKEN_FAILURE.getMessage(),
                        getWechatErrCodeAndDes(JsonUtils.parseObject(mapResult, WechatCommonResponse.class))
                );
            }
        } catch (IOException e) {
            response.setResultCodeAndMessage(
                    ResponseEnum.WECHAT_ACCESS_TOKEN_EXCEPTION.getCode(),
                    ResponseEnum.WECHAT_ACCESS_TOKEN_EXCEPTION.getMessage()
            );

            logger.error("WechatAuthServiceImpl.getWechatAuthMedicalAccessToken.IOException", e);
        } catch (DocumentException e) {
            response.setResultCodeAndMessage(
                    ResponseEnum.WECHAT_ACCESS_TOKEN_EXCEPTION.getCode(),
                    ResponseEnum.WECHAT_ACCESS_TOKEN_EXCEPTION.getMessage()
            );

            logger.error("WechatAuthServiceImpl.getWechatAuthMedicalAccessToken.DocumentException", e);
        }

        return response;
    }

    /**
     * 获取微信jsapi_ticket
     *
     * @param data
     * @return
     */
    public ResponseObject getWechatAuthJsapiTicket(String data) {
        logger.info("WechatAuthServiceImpl.getWechatJsapiTicket.data -> {}", data);

        ResponseObject response = new ResponseObject();

        Map<String, String> params = JsonUtils.parseObject(data, Map.class);

        String accessToken = params.get("access_token");

        String url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket" +
                "?access_token=" + accessToken +
                "&type=jsapi";

        logger.info("WechatAuthServiceImpl.getWechatJsapiTicket.url -> {}", url);
        try {
            String result = HttpUtil.get(url);
            logger.info("WechatAuthServiceImpl.getWechatJsapiTicket.result -> {}", result);

            WechatJsapiTicketResponse jsapiTicket = JsonUtils.parseObject(result, WechatJsapiTicketResponse.class);

            if (jsapiTicket != null && !StringUtils.isEmpty(jsapiTicket.getTicket())) {
                response.setResultObject(jsapiTicket);
            } else {
                response.setResultCodeAndMessageAndResult(
                        ResponseEnum.WECHAT_JSAPI_TICKET_FAILURE.getCode(),
                        ResponseEnum.WECHAT_JSAPI_TICKET_FAILURE.getMessage(),
                        getWechatErrcodeAndmsg(JsonUtils.parseObject(result, WechatCommonResponse.class))
                );
            }
        } catch (IOException e) {
            response.setResultCodeAndMessage(
                    ResponseEnum.WECHAT_JSAPI_TICKET_EXCEPTION.getCode(),
                    ResponseEnum.WECHAT_JSAPI_TICKET_EXCEPTION.getMessage()
            );

            logger.error("WechatAuthServiceImpl.getWechatJsapiTicket.exception", e);
        }

        return response;
    }

    /**
     * 微信验证实名
     *
     * @param data
     * @return
     */
    public ResponseObject verifyWechatAuthName(String data) {
        logger.info("WechatAuthServiceImpl.getWechatJsapiTicket.data -> {}", data);

        ResponseObject response = new ResponseObject();

        try {
            Map<String, String> requestMap = JsonUtils.parseObject(data, Map.class);
            logger.info("WechatPayServiceImpl.verifyWechatAuthName.requestMap -> {}", JsonUtils.toJsonString(requestMap));

            String accessToken = requestMap.get("access_token");
            String apiSecret = requestMap.get("api_secret");

            String username = requestMap.get("name");
            String idcard = requestMap.get("idcard");

            requestMap.remove("access_token");
            requestMap.remove("api_secret");

            requestMap.put("sign", SignUtil.wechatPaySign(requestMap, apiSecret));

            String xml = XMLUtil.buildMapXML(requestMap);
            logger.info("WechatPayServiceImpl.verifyWechatAuthName.xml -> {}", xml);

            String requestUrl = String.format(this.getConfig(Wechat.WECHAT_MEDICAL_VERIFY), accessToken);
            logger.info("WechatPayServiceImpl.verifyWechatAuthName.requestUrl -> {}", requestUrl);

            String result = HttpUtil.post(xml, requestUrl);
            logger.info("WechatPayServiceImpl.verifyWechatAuthName.result -> {}", result);

            Map<String, String> resultMap = XMLUtil.xmlToMap(result);
            logger.info("WechatPayServiceImpl.verifyWechatAuthName.resultMap -> {}", JsonUtils.toJsonString(resultMap));

            WechatPayResponse verifyResponse = JsonUtils.parseObject(resultMap, WechatPayResponse.class);
            logger.info("WechatPayServiceImpl.verifyWechatAuthName.verifyResponse -> {}", JsonUtils.toJsonString(verifyResponse));

            if (verifyResponse.isReturnCodeSuccess() && verifyResponse.isResultCodeSuccess()) {
                logger.info("Name:{}, Card:{} verification passed.", username, idcard);
            } else {
                response.setResultCodeAndMessageAndResult(
                        ResponseEnum.WECHAT_PAY_FAIL.getCode(),
                        ResponseEnum.WECHAT_PAY_FAIL.getMessage(),
                        getWechatErrCodeAndDes(JsonUtils.parseObject(resultMap, WechatCommonResponse.class))
                );
            }
        } catch (Exception e) {
            logger.error("WechatPayServiceImpl.verifyWechatAuthName.exception", e);
            response.setResultCodeAndMessage(
                    ResponseEnum.WECHAT_PAY_EXCEPTION.getCode(),
                    ResponseEnum.WECHAT_PAY_EXCEPTION.getMessage()
            );
        }

        return response;
    }

}
